#include <sum_gpio.h>
#include <sum_rcu.h>
#include <sum_usart.h>
#include <sys_mem.h>
#include <util_trans.h>

#define APB2_FREQ_DEFAULT 8000000

// RCU中将GPIOA、GPIOB和USART0上电
static void _enable_gpioab_usart0(void) {
	rcu_apb2_s apb2 = {
		.apb2_0_7.GPIOA = 1,
		.apb2_0_7.GPIOB = 1,
		.apb2_8_15.USART0 = 1,
	};
	rcu_apb2_en_di(apb2);
}

// 配置GPIOB全部为输出
static void _setup_gpiob_output(void) {
	// 一次性配置B0到B7。引脚号均不大于7，因此由CTL0配置。
	// 所有引脚配置成最普通的输出（GP、推挽、低速）
	gpio_ctl_0_7_s ctl_0_7 = {
		.pin0_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin1_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin2_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin3_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin4_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin5_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin6_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin7_ctl = GPIO_OUT_GP_PP_2MHZ,
	};
	gpio_setup_pin_0_7(GPIOB_Q, ctl_0_7);

	// 一次性配置B8到B15。引脚号均大于7，因此由CTL1配置。
	gpio_ctl_8_15_s ctl_8_15 = {
		.pin8_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin9_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin10_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin11_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin12_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin13_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin14_ctl = GPIO_OUT_GP_PP_2MHZ,
		.pin15_ctl = GPIO_OUT_GP_PP_2MHZ,
	};
	gpio_setup_pin_8_15(GPIOB_Q, ctl_8_15);
}

// 配置A9为AF输出，A10为浮空输入。
static void _setup_gpafio(void) {
	gpio_ctl_8_15_s ctl = {
		// A9的配置：低速输出、AF、推挽
		.pin9_ctl = GPIO_OUT_AF_PP_2MHZ,

		// A10的配置：输入、浮空
		.pin10_ctl = GPIO_IN_FLOAT,
	};
	gpio_setup_pin_8_15(GPIOA_Q, ctl);
}

// 使能USART0本身，以及其发送功能。
static void _enable_usart0_send(void) {
	usart_ctl0_expl_s ctl0 = {
		.trans_en = 1,
		.usart_en = 1,
	};
	usart_setup_0(USART0_Q, ctl0);
}

// 手动计算mask后pin的结果
static gpio_pins_s _cal_pins_manual(gpio_pins_s current_pins,
				    mask_pins_s mask_pins) {
	gpio_pins_s result_pins = current_pins;
	if (mask_pins.mask.PIN0) {
		result_pins.PIN0 = mask_pins.pins.PIN0;
	}
	if (mask_pins.mask.PIN1) {
		result_pins.PIN1 = mask_pins.pins.PIN1;
	}
	if (mask_pins.mask.PIN2) {
		result_pins.PIN2 = mask_pins.pins.PIN2;
	}
	if (mask_pins.mask.PIN3) {
		result_pins.PIN3 = mask_pins.pins.PIN3;
	}
	if (mask_pins.mask.PIN4) {
		result_pins.PIN4 = mask_pins.pins.PIN4;
	}
	if (mask_pins.mask.PIN5) {
		result_pins.PIN5 = mask_pins.pins.PIN5;
	}
	if (mask_pins.mask.PIN6) {
		result_pins.PIN6 = mask_pins.pins.PIN6;
	}
	if (mask_pins.mask.PIN7) {
		result_pins.PIN7 = mask_pins.pins.PIN7;
	}
	if (mask_pins.mask.PIN8) {
		result_pins.PIN8 = mask_pins.pins.PIN8;
	}
	if (mask_pins.mask.PIN9) {
		result_pins.PIN9 = mask_pins.pins.PIN9;
	}
	if (mask_pins.mask.PIN10) {
		result_pins.PIN10 = mask_pins.pins.PIN10;
	}
	if (mask_pins.mask.PIN11) {
		result_pins.PIN11 = mask_pins.pins.PIN11;
	}
	if (mask_pins.mask.PIN12) {
		result_pins.PIN12 = mask_pins.pins.PIN12;
	}
	if (mask_pins.mask.PIN13) {
		result_pins.PIN13 = mask_pins.pins.PIN13;
	}
	if (mask_pins.mask.PIN14) {
		result_pins.PIN14 = mask_pins.pins.PIN14;
	}
	if (mask_pins.mask.PIN15) {
		result_pins.PIN15 = mask_pins.pins.PIN15;
	}
	return result_pins;
}

// 将pins转化为整数
static u32_s _pins_to_u32(gpio_pins_s pins) {
	union {
		gpio_pins_s p;
		u32_s u;
	} pu = {
		.p = pins,
	};
	return pu.u;
}

// 向串口阻塞发送1字节的函数，也是trans_write系列函数的参数。
static void _send(u32_s byte) {
	usart_wb_byte(USART0_Q, byte);
}

__attribute__((noreturn, section(".MAIN"))) void user_main(void) {
	// 未定义全局变量和静态局部变量，因此不需要scatter_load。
	// mem_scatter_load();
	_enable_gpioab_usart0();
	_setup_gpiob_output();
	_setup_gpafio();
	usart_set_baud_rate(USART0_Q, 115200, APB2_FREQ_DEFAULT);
	_enable_usart0_send();

	// mask_pins值取自flash
	extern const u32_s data_lma;
	const u32_s* start_p = (const u32_s*)4;
	const u32_s* endn_p = &data_lma;
	const u32_s* p = start_p;
	trans_write_str("start_p = 0x", _send);
	trans_write_uhex((u32_s)start_p, 8, _send);
	trans_write_str(", endn_p = 0x", _send);
	trans_write_uhex((u32_s)endn_p, 8, _send);
	trans_write_str(".\r\n", _send);

	// 当前GPIOB的引脚值
	gpio_pins_s gpiob_pins = gpio_get_output_pull_pins(GPIOB_Q);
	trans_write_str("init_gpiob = 0x", _send);
	trans_write_uhex(_pins_to_u32(gpiob_pins), 4, _send);
	trans_write_str(".\r\n", _send);

	while (1) {
		union {
			mask_pins_s mp;
			u32_s u;
		} mpu = {
			.u = *p,
		};
		mask_pins_s mask_pins = mpu.mp;
		trans_write_str("mask = 0x", _send);
		trans_write_uhex(_pins_to_u32(mask_pins.mask), 4, _send);
		trans_write_str(", pins = 0x", _send);
		trans_write_uhex(_pins_to_u32(mask_pins.pins), 4, _send);

		// 手动计算mask后的理论结果
		gpio_pins_s manual_result =
			_cal_pins_manual(gpiob_pins, mask_pins);

		// 使用mask_set函数后GPIOB的实际结果
		gpio_mask_set_pins(GPIOB_Q, mask_pins);
		gpiob_pins = gpio_get_output_pull_pins(GPIOB_Q);

		u32_s manual_result_u32 = _pins_to_u32(manual_result);
		u32_s gpiob_pins_u32 = _pins_to_u32(gpiob_pins);
		trans_write_str(".\r\nmanual_result = 0x", _send);
		trans_write_uhex(manual_result_u32, 4, _send);
		trans_write_str(", real_result = 0x", _send);
		trans_write_uhex(gpiob_pins_u32, 4, _send);
		trans_write_str(".\r\n", _send);

		// 若两者相等，正常。
		if (gpiob_pins_u32 == manual_result_u32) {
			trans_write_str("The results are equal.\r\n", _send);
		} else {
			trans_write_str("Error! The results are not equal!\r\n",
					_send);
			while (1)
				;
		}
		p++;
		if (p == endn_p) {
			p = start_p;
		}
	}
}
